package cn.cas.mango.service;


import cn.cas.mango.util.Pair;
import cn.cas.mango.util.TimeUtil;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import co.elastic.clients.elasticsearch.core.SearchRequest;
import co.elastic.clients.elasticsearch.core.SearchResponse;
import co.elastic.clients.elasticsearch.core.bulk.BulkOperation;
import co.elastic.clients.elasticsearch.core.search.Hit;
import co.elastic.clients.elasticsearch.core.search.TotalHits;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RequestService {



  @Autowired
  private ElasticsearchClient client;


  public  <T> Pair<TotalHits,  List<Hit<T>>> getLarge(SearchRequest.Builder builder1, SearchRequest.Builder builder2, Class<T> tclass, int size) {
    long total;
    List<Hit<T>> ret = new ArrayList<>();
    TotalHits hits;
    if (size != -1) {
      hits = TotalHits.of(x->x.value(size));
      total = size;
    } else {
      try {
        SearchRequest searchRequest = builder1.size(0).trackTotalHits(v->v.enabled(true)).build();
        log.info("search request with error size: {}" ,searchRequest);
        SearchResponse<Map> search = client.search(searchRequest, Map.class);
        hits = search.hits().total();
        total = hits.value();
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
    }

    int batch = 1000;
    for (int i = 0; i <= (total - 1) / batch; i++) {
      int finalI = i;
      SearchResponse<T> search = null;
      SearchRequest.Builder builder = new SearchRequest.Builder();
      SearchRequest build = builder2.from(finalI * batch).size(batch).build();
      builder.index(build.index());
      builder.query(build.query());
      builder.source(build.source());
      builder.highlight(build.highlight());
      builder.aggregations(build.aggregations());
      builder.sort(build.sort());
      builder.minScore(build.minScore());
      builder.trackTotalHits(build.trackTotalHits());
      builder2 = builder;
      try {
        search = client.search(build, tclass);
      } catch (IOException e) {
        throw new RuntimeException(e);
      }
      List<Hit<T>> collect = search.hits().hits().stream().collect(Collectors.toList());
      ret.addAll(collect);
    }
    return new Pair<>(hits, ret);
  }

}
